#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "vector.h"

#define VECTOR_MINALLOC 10                   /* minimum number of elements */
#define VECTOR_MAXEXTRA 1000000 /* maximum number of extra elements */

vector * vector_alloc(int numalloc)
{
  vector * vec;

  /* allocate at least some minimum number of elements */
  if (numalloc < VECTOR_MINALLOC)
    numalloc = VECTOR_MINALLOC;
  
  vec = (vector *)malloc(sizeof(*vec));
  vec->numelem_vector = 0;
  vec->numalloc_vector = numalloc;
  vec->pelems_vector = (double *)malloc(numalloc
                                        * sizeof(*vec->pelems_vector));
  if (!vec->pelems_vector)
  {
    fprintf(stderr, "Error: out of memory\n");
    exit(-1);
  }

  return vec;
}

void vector_free(vector * vec)
{
  free(vec->pelems_vector);
  free(vec);
}

void vector_append(vector * vec, double val)
{
  double * pelems;
  int numalloc;
  
  /* if we already have the memory then there is nothing more to it */
  if (vec->numelem_vector < vec->numalloc_vector)
  {
    vec->pelems_vector[vec->numelem_vector ++] = val;
    return;
  }

  /* compute the size of the memory needed and allocate it */
  numalloc = vec->numalloc_vector * 2 + VECTOR_MINALLOC;
  if ((numalloc - vec->numalloc_vector) > VECTOR_MAXEXTRA)
    numalloc = vec->numalloc_vector + VECTOR_MAXEXTRA;
  
  pelems = (double *)malloc(numalloc * sizeof(*pelems));
  if (!pelems)
  {
    fprintf(stderr, "Error: out of memory\n");
    exit(-1);
  }
  
  /* move the memory from the old vector to the new one */
  memcpy(pelems, vec->pelems_vector, sizeof(*pelems) * vec->numelem_vector);
  free(vec->pelems_vector);
  vec->pelems_vector = pelems;
  vec->numalloc_vector = numalloc;
  
  assert(vec->numelem_vector < vec->numalloc_vector);
  vec->pelems_vector[vec->numelem_vector ++] = val;  
}

/* add the elements of the vector */
double vector_sum(vector * vec)
{
  double result;
  int i;                                     /* loop counter */
  
  result = 0;
  for (i=0; i<vec->numelem_vector; i++)
    result += VECTOR_IDX(vec, i);

  return result;
}

